package models

import (
	"errors"
	"fmt"
	"github.com/jinzhu/gorm"
	"github.com/lib/pq"
	"zhanyan/pac/util"
)

type User struct {
	ID           int            `json:"id";gorm:"primary_key"`
	Username     string         `json:"username,omitempty"`
	Password     string         `json:"password,omitempty"`
	Name         string         `json:"name,omitempty"`
	SchoolCode   string         `json:"school_code,omitempty"`
	Introduction string         `json:"introduction,omitempty"`
	Power        int            `json:"power,omitempty"`                                 // 如果是教师就为1，如果是学生就为0
	ChatNames    pq.StringArray `json:"chat_names,omitempty" gorm:"type:varchar(255)[]"` // 用户所在聊天室的名字列表
}

type Teacher struct {
	User
	TeacherCode string `json:"teacher_code,omitempty"`
	Phone       string `json:"phone,omitempty"`
	Classroom   []Classroom
}

type Student struct {
	User
	StudentCode string `json:"student_code,omitempty"`
	Seat        Seat
}

// CheckUser 检查用户是否存在
func CheckUser(username, password string) (bool, error) {
	var teacher Teacher
	var student Student
	err1 := db.Select("id").Where(Teacher{User: User{Username: username, Password: password}}).First(&teacher).Error
	err2 := db.Select("id").Where(Student{User: User{Username: username, Password: password}}).First(&student).Error

	if (err1 != nil && err2 != nil) && (err1 != gorm.ErrRecordNotFound && err2 != gorm.ErrRecordNotFound) {
		return false, errors.New(fmt.Sprintf("两个错误分别是：%v，%v", err1, err2))
	}

	if teacher.ID+student.ID > 0 {
		return true, nil
	}

	return false, util.UserNotExistError
}

// CheckTeacher 检查教师是否存在
func CheckTeacher(username, password string) (bool, error) {
	var teacher Teacher
	err1 := db.Where(Teacher{User: User{Username: username, Password: password}}).First(&teacher).Error

	if err1 != nil && err1 != gorm.ErrRecordNotFound {
		return false, err1
	}

	if teacher.ID > 0 {
		return true, nil
	}

	return false, nil
}

// CheckTeacherById 通过id检查教师是否存在
func CheckTeacherById(id int) (bool, error) {
	var teacher = Teacher{User: User{ID: id}}
	err1 := db.First(&teacher).Error
	if err1 != nil && err1 != gorm.ErrRecordNotFound {
		return false, err1
	}

	if teacher.ID > 0 {
		return true, nil
	}

	return false, nil
}

// CheckStudent 检查学生是否存在
func CheckStudent(username, password string) (bool, error) {
	var student Student
	err1 := db.Where(Student{User: User{Username: username, Password: password}}).First(&student).Error

	if err1 != nil && err1 != gorm.ErrRecordNotFound {
		return false, err1
	}

	if student.ID > 0 {
		return true, nil
	}

	return false, nil
}

// QueryStudent 根据用户名和密码查询学生是否存在
func QueryStudent(username, password string) (bool, error) {
	var student Student
	err1 := db.Where(Student{User: User{Username: username, Password: password}}).First(&student).Error

	if err1 != nil && err1 != gorm.ErrRecordNotFound {
		return false, err1
	}

	if student.ID > 0 {
		return true, nil
	}

	return false, nil
}

// CheckStudentById 通过id检查学生是否存在
func CheckStudentById(id int) (bool, error) {
	var student = Student{User: User{ID: id}}
	err1 := db.First(&student).Error

	if err1 != nil && err1 != gorm.ErrRecordNotFound {
		return false, err1
	}

	if student.ID > 0 {
		return true, nil
	}

	return false, nil
}

// CheckStudentByName 通过username检查学生是否存在
func CheckStudentByName(username string) (*Student, error) {
	var student Student

	err1 := db.Where(Student{User: User{Username: username}}).First(&student).Error
	if err1 != nil && err1 != gorm.ErrRecordNotFound {
		return nil, err1
	}

	if student.ID > 0 {
		return &student, nil
	}

	return nil, nil
}

// CheckTeacherByName 通过username检查学生是否存在
func CheckTeacherByName(username string) (*Teacher, error) {
	var teacher Teacher

	err1 := db.Where(Teacher{User: User{Username: username}}).First(&teacher).Error
	if err1 != nil && err1 != gorm.ErrRecordNotFound {
		return nil, err1
	}

	if teacher.ID > 0 {
		return &teacher, nil
	}

	return nil, nil
}

// AddTeacher 添加教师
func AddTeacher(teacher *Teacher) (int, error) {
	if err := db.Create(teacher).Error; err != nil {
		return 0, util.UserNotAddedError
	}
	id := teacher.ID
	return id, nil
}

// AddStudent 添加教师
func AddStudent(student *Student) (int, error) {
	if err := db.Create(student).Error; err != nil {
		return 0, util.UserNotAddedError
	}
	id := student.ID
	return id, nil
}

// AddUser 添加用户
func AddUser(user *User) error {
	if err := db.Create(user).Error; err != nil {
		return util.UserNotAddedError
	}
	return nil
}

// UpdateUser 修改用户
func UpdateUser(user *User) error {
	if err := db.Update(user).Error; err != nil {
		return util.UserUpdateError
	}
	return nil
}

// UpdateTeacher 修改教师
func UpdateTeacher(t *Teacher) error {
	if err := db.Save(t).Error; err != nil {
		return util.UserUpdateError
	}
	return nil
}

// UpdateStudent 修改学生
func UpdateStudent(s *Student) error {
	if err := db.Save(s).Error; err != nil {
		return util.UserUpdateError
	}
	return nil
}

// DeleteTeacher 删除教师
func DeleteTeacher(id int) error {
	if err := db.Delete(&Teacher{}, id).Error; err != nil {
		return util.UserDeleteError
	}
	return nil
}

// DeleteTeacherInClass 删除教师与教室的关联
func DeleteTeacherInClass(tid, cid int) error {
	teacher := Teacher{}
	teacher.ID = tid
	classroom := Classroom{ID: cid}
	err := db.Model(&teacher).Association("Classroom").Delete(&classroom).Error
	if err != nil {
		return util.ClearTeacherRelationshipError
	}
	return nil
}

// DeleteTeacherInAllClass 删除教师与所有教室的关联
func DeleteTeacherInAllClass(tid int) error {
	teacher := Teacher{}
	teacher.ID = tid
	err := db.Model(&teacher).Association("Classroom").Clear().Error
	if err != nil {
		return util.ClearTeacherRelationshipError
	}
	return nil
}

// DeleteStudent 删除学生
func DeleteStudent(id int) error {
	if err := db.Delete(&Student{}, id).Error; err != nil {
		return util.UserDeleteError
	}
	return nil
}

// QueryStudentById 通过id获取学生信息
func QueryStudentById(id int) (*Student, error) {
	student := &Student{}
	student.ID = id
	if err := db.Preload("Seat").First(student).Error; err != nil {
		return nil, util.UserQueryError
	}
	return student, nil
}

// QueryTeacherById 通过id获取老师信息
func QueryTeacherById(id int) (*Teacher, error) {
	teacher := &Teacher{}
	teacher.ID = id
	if err := db.First(teacher).Error; err != nil {
		return nil, util.UserQueryError
	}
	return teacher, nil
}

// QueryStudents 检索所有学生
func QueryStudents() (*[]Student, error) {
	students := &[]Student{}
	if err := db.Find(students).Error; err != nil {
		return nil, util.UserQueryError
	}
	studentss := []Student{}
	for _, student := range *students {
		seat := Seat{}
		db.Model(&student).Association("Seat").Find(&seat)
		student.Seat = seat
		studentss = append(studentss, student)
	}
	return &studentss, nil
}

// QueryTeachers 检索所有教师
func QueryTeachers() (*[]Teacher, error) {
	teachers := &[]Teacher{}
	if err := db.Find(teachers).Error; err != nil {
		return nil, util.UserQueryError
	}
	return teachers, nil
}

// QueryStudentsPage 分页查找学生
func QueryStudentsPage(pageSize int, pageCode int) (*[]Student, error) {
	students := &[]Student{}
	err := db.Limit(pageSize).Offset(pageCode * pageSize).Preload("Seat").Find(&students).Error
	if err != nil {
		return nil, util.UserQueryError
	}
	studentss := []Student{}
	for _, student := range *students {
		seat := Seat{}
		db.Model(&student).Association("Seat").Find(&seat)
		student.Seat = seat
		studentss = append(studentss, student)
	}
	return &studentss, nil
}

// QueryTeachersPage 分页查找教师
func QueryTeachersPage(pageSize int, pageCode int) (*[]Teacher, error) {
	teachers := &[]Teacher{}
	fmt.Println("models.Teacher page size: ", pageSize, "pagecode", pageCode)
	err := db.Limit(pageSize).Offset(pageCode * pageSize).Find(&teachers).Error
	if err != nil {
		return nil, util.UserQueryError
	}
	return teachers, nil
}
